﻿using System.Collections.Generic;
using System;

namespace DARE
{
    public static class CAnimationMgr
    {
        #region Fields

        private static Dictionary<string, CAnimConfig> m_anims;
        private static readonly Dictionary<string, IAnimation> m_animation;

        #endregion

        #region CONST

        //public const string SKELETON = "SKELETON";
        public const string ANIMATION = "ANIMATION";
        public const string HIERARCHY = "SKELETON";

        #endregion

        #region CTOR

        static CAnimationMgr()
        {
            //m_animsBySkeleton = new Dictionary<string, IAnimation>();
            //m_anims = new Dictionary<string, CAnimConfig>();

            m_anims = new Dictionary<string, CAnimConfig>();
            m_animation = new Dictionary<string, IAnimation>();
        }

        #endregion

        #region Method

        public static void Clear()
        {
            m_animation.Clear();
            m_anims.Clear();
        }

        public static void EditAnimation(string name, int duration)
        {
            if (!m_anims.ContainsKey(name))
                return;
            //IAnimation anim = m_anims[name].Animation;
            //m_anims.Remove(name);
            //m_anims.Add(name, new CAnimConfig(anim, name, begin, end));

            m_anims[name].CutAnimation(duration);

        }

        internal static CAnimConfig GetAnimationByName(string name) //, bool _skeletonAnimation
        {
            //if (m_anims == null)
            //{
            //    m_anims = new Dictionary<string, CAnimConfig>();
            //    foreach (var el in m_animation)
            //        AddAnimationsConfig(el.Value);
            //}
                if (m_anims.ContainsKey(name))
                return m_anims[name].AnimClone();
            return null;
        }

        public static bool AddAnimation(IAnimation a)
        {
            if (a == null || m_animation.ContainsKey(a.Name))
                    return false;
            //foreach (var el in m_animation)
                AddAnimationsConfig(a);
            m_animation.Add(a.Name, a);
            return true;
            }

        private static void AddAnimationsConfig(IAnimation a)
            {
            foreach (var anim in a.GetAnims())
            {
                if (m_anims.ContainsKey(anim.AnimName))
                    continue;
                anim.Animation = a;
                m_anims.Add(anim.AnimName, anim);
            }
        }

        public static bool LoadAnimation(string name)
        {
            try
            {
                CResourceMgr.Load<CAnimation>(name);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        //public static List<string> ListOfPosibleAnimationBySkeleton(CHierarchy _skeleton)
        //{
        //    List<string> _anims = new List<string>();
        //    foreach (var elem in m_animsBySkeleton)
        //    {
        //        if (CouldPlayThisAnimationBySkeleton(elem.Key, _skeleton))
        //            _anims.Add(elem.Key);
        //    }
        //    return _anims;
        //}

        //private static bool CouldPlayThisAnimationBySkeleton(string name, CHierarchy _skeleton)
        //{
        //    if (!m_animsBySkeleton.ContainsKey(name))
        //        return false;

        //    return TestViabilityAnim(m_animsBySkeleton[name], _skeleton);
        //}

        public static IAnimation GetIAnimation(string animation)
        {
            if (m_animation.ContainsKey(animation))
                return m_animation[animation];
            return null;
        }

        public static List<string> ListOfPosibleAnimation(CHierarchy _hierachy)
        {
            List<string> _anims = new List<string>();
            foreach (var elem in m_anims)
            {
                if (CouldPlayThisAnimation(elem.Key, _hierachy))
                    _anims.Add(elem.Key);
            }
            return _anims;
        }

        private static bool CouldPlayThisAnimation(string name, CHierarchy _skeleton)
        {
            if (!m_anims.ContainsKey(name))
                return false;

            return TestViabilityAnim(m_anims[name].Animation, _skeleton);
        }

        private static bool TestViabilityAnim(IAnimation anim, CHierarchy _skeleton)
        {
            foreach (var elem in anim.Hierarchy.Nodes)
            {
                bool found = false;
                foreach (var item in _skeleton.Nodes)
                {
                    if (elem.Name == item.Name)
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                    return false;
            }
            return true;
        }

        #endregion
    }
}
